<script setup>
import { onMounted, onBeforeUnmount, reactive, ref } from 'vue'
import { fetchMenuList } from '@/api/menuApi'
import { fetchCurrentRole, postAddRole } from '@/api/roleApi'
import { ElMessage } from 'element-plus'
import logger from '@/utils/logger'

const props = defineProps({
  dealerRoleId: {
    type: String,
    default: null,
  },
})

const emit = defineEmits(['close', 'success'])

/**
 * @description 角色信息
 */
let roleInfo = reactive({
  dealerRoleId: '',
  roleName: '',
  dealerMenuIdList: [],
})

/**
 * @description 菜单列表
 */
let menuList = ref([])

/**
 * @description 表单引用
 */
const roleFormRef = ref(null)

/**
 * @description 树组件引用
 */
const menuTreeRef = ref(null)

/**
 * @description 表单规则
 */
const rules = {
  roleName: [
    { required: true, message: '请输入角色名称', trigger: 'blur' },
    { min: 2, max: 20, message: '角色名称长度应为2-20个字符', trigger: 'blur' },
  ],
}

/**
 * @description 加载中状态
 */
const loading = ref(false)

/**
 * @description 重置表单和数据
 */
const resetForm = () => {
  if (roleFormRef.value) {
    roleFormRef.value.resetFields()
  }
  roleInfo.dealerRoleId = ''
  roleInfo.roleName = ''
  roleInfo.dealerMenuIdList = []
  menuList.value = []
  selectAll.value = false
  isIndeterminate.value = false
  parentChildLink.value = true // 重置为默认开启父子联动
}

/**
 * @description 获取菜单列表
 */
const handleFetchMenuList = async () => {
  try {
    const res = await fetchMenuList()
    menuList.value = res.data
  } catch (error) {
    logger.error('获取菜单列表失败', error)
    ElMessage.error('获取菜单列表失败')
  }
}

/**
 * @description 获取当前角色信息
 */
const handleFetchRoleInfo = async (id) => {
  try {
    const res = await fetchCurrentRole(id)
    const { dealerRoleId, roleName, dealerMenuIdList, menuTreeByRoleId } = res.data

    roleInfo.dealerRoleId = dealerRoleId
    roleInfo.roleName = roleName

    // 处理菜单ID列表
    if (dealerMenuIdList && dealerMenuIdList.length > 0) {
      // 如果API直接返回了dealerMenuIdList数组，直接使用
      roleInfo.dealerMenuIdList = dealerMenuIdList
    } else if (menuTreeByRoleId && menuTreeByRoleId.length > 0) {
      // 如果API返回了menuTreeByRoleId结构，从中提取选中的菜单ID
      // 注意：我们需要从menuTreeByRoleId中明确提取checked为true的ID
      // 而不是从所有返回的菜单中获取ID
      const checkedIds = extractCheckedMenuIds(menuTreeByRoleId)
      roleInfo.dealerMenuIdList = checkedIds

      // 打印日志，方便调试
      console.log('提取的选中菜单ID:', checkedIds)
    } else {
      roleInfo.dealerMenuIdList = []
    }
  } catch (error) {
    logger.error('获取角色信息失败', error)
    ElMessage.error('获取角色信息失败')
  }
}

/**
 * @description 从菜单树中提取已选中的菜单ID
 * @param {Array} menuTree 菜单树数组
 * @return {Array} 选中的菜单ID数组
 */
const extractCheckedMenuIds = (menuTree) => {
  const checkedIds = []

  // 递归遍历菜单树
  const traverse = (menus) => {
    if (!menus || !menus.length) return

    menus.forEach((menu) => {
      // 只有明确标记为checked: true的菜单才会被添加
      if (menu.checked === true) {
        checkedIds.push(menu.id)
      }

      // 递归处理子菜单
      if (menu.children && menu.children.length) {
        traverse(menu.children)
      }
    })
  }

  traverse(menuTree)
  return checkedIds
}

/**
 * @description 提交表单
 */
const handleSubmit = async () => {
  if (!roleFormRef.value) return

  // 获取当前选中的节点ID数组
  if (menuTreeRef.value) {
    if (parentChildLink.value) {
      // 父子联动模式：获取所有选中的节点（包括子节点）
      roleInfo.dealerMenuIdList = menuTreeRef.value.getCheckedKeys()
    } else {
      // 独立选择模式：获取选中的节点（不包括半选节点）
      roleInfo.dealerMenuIdList = menuTreeRef.value.getCheckedKeys()
    }
  }

  await roleFormRef.value.validate(async (valid) => {
    if (valid) {
      try {
        loading.value = true
        const res = await postAddRole(roleInfo)
        if (res.code === 200) {
          ElMessage.success(props.dealerRoleId ? '修改成功' : '添加成功')
          emit('success')
          emit('close')
        } else {
          ElMessage.error(res.msg)
        }
      } catch (error) {
        logger.error('保存角色失败', error)
        ElMessage.error(props.dealerRoleId ? '修改失败' : '添加失败')
      } finally {
        loading.value = false
      }
    }
  })
}

/**
 * @description 取消操作
 */
const handleCancel = () => {
  resetForm()
  emit('close')
}

/**
 * @description 全选状态
 */
const selectAll = ref(false)

/**
 * @description 半选状态（部分选中）
 */
const isIndeterminate = ref(false)

/**
 * @description 父子联动状态
 */
const parentChildLink = ref(true)

/**
 * @description 切换父子联动模式
 */
const handleParentChildLinkChange = () => {
  // 当切换父子联动模式时，可以选择是否重置当前选择
  // 这里保持当前选择不变，只是改变联动模式
}

/**
 * @description 全选/取消全选
 */
const handleSelectAll = () => {
  if (!menuTreeRef.value) return

  if (selectAll.value) {
    // 全选：设置所有节点为选中状态
    const allNodeKeys = getAllNodeKeys(menuList.value)
    menuTreeRef.value.setCheckedKeys(allNodeKeys)
    isIndeterminate.value = false
  } else {
    // 取消全选：清空所有选中状态
    menuTreeRef.value.setCheckedKeys([])
    isIndeterminate.value = false
  }
}

/**
 * @description 获取所有节点的key
 */
const getAllNodeKeys = (nodes) => {
  const keys = []
  const traverse = (nodeList) => {
    nodeList.forEach((node) => {
      keys.push(node.id)
      if (node.children && node.children.length > 0) {
        traverse(node.children)
      }
    })
  }
  traverse(nodes)
  return keys
}

/**
 * @description 树选择变化时的处理
 */
const handleCheckChange = () => {
  // 检查全选状态和半选状态
  if (menuTreeRef.value) {
    const checkedKeys = menuTreeRef.value.getCheckedKeys()
    const allKeys = getAllNodeKeys(menuList.value)

    if (checkedKeys.length === 0) {
      // 没有选中任何项
      selectAll.value = false
      isIndeterminate.value = false
    } else if (checkedKeys.length === allKeys.length) {
      // 全部选中
      selectAll.value = true
      isIndeterminate.value = false
    } else {
      // 部分选中
      selectAll.value = false
      isIndeterminate.value = true
    }
  }
}

onMounted(async () => {
  await handleFetchMenuList()
  console.log(props.dealerRoleId)

  if (props.dealerRoleId) {
    await handleFetchRoleInfo(props.dealerRoleId)
    // 编辑模式下，检查全选状态和半选状态
    setTimeout(() => {
      handleCheckChange()
    }, 100)
  }
})

// 组件销毁前清理资源
onBeforeUnmount(() => {
  resetForm()
})

// 暴露方法给父组件
defineExpose({
  resetForm,
})
</script>

<template>
  <div class="add-role-container">
    <el-form
      ref="roleFormRef"
      :model="roleInfo"
      :rules="rules"
      label-width="100px"
      label-position="right"
    >
      <el-form-item label="角色名称" prop="roleName">
        <el-input
          v-model="roleInfo.roleName"
          placeholder="请输入角色名称"
          maxlength="20"
          show-word-limit
        />
      </el-form-item>

      <el-form-item label="菜单权限" v-if="menuList.length > 0">
        <div class="menu-tree-container">
          <!-- 功能控制 -->
          <div class="control-container">
            <div class="control-item">
              <el-checkbox
                v-model="selectAll"
                @change="handleSelectAll"
                :indeterminate="isIndeterminate"
              >
                全选
              </el-checkbox>
            </div>
            <div class="control-item">
              <el-checkbox v-model="parentChildLink" @change="handleParentChildLinkChange">
                父子联动
              </el-checkbox>
              <el-tooltip content="开启后，选择父级菜单将自动选择所有子级菜单" placement="top">
                <el-icon
                  style="margin-left: 4px; color: var(--el-text-color-secondary); cursor: help"
                >
                  <LineMdQuestionCircle />
                </el-icon>
              </el-tooltip>
            </div>
          </div>

          <!-- 菜单树 -->
          <el-tree
            ref="menuTreeRef"
            :data="menuList"
            show-checkbox
            node-key="id"
            default-expand-all
            :check-strictly="!parentChildLink"
            :props="{
              label: 'text',
              children: 'children',
            }"
            :default-checked-keys="roleInfo.dealerMenuIdList"
            @check="handleCheckChange"
          >
            <template #default="{ node, data }">
              <span class="custom-tree-node">
                <el-icon v-if="data.iconCls">
                  <component :is="data.iconCls" />
                </el-icon>
                <span class="menu-text">{{ node.label }}</span>
              </span>
            </template>
          </el-tree>
        </div>
      </el-form-item>

      <div class="buttons">
        <el-button @click="handleCancel">
          <template #icon>
            <el-icon><LineMdClose /></el-icon>
          </template>
          取消
        </el-button>
        <el-button type="primary" @click="handleSubmit" :loading="loading">
          <template v-if="!props.dealerRoleId" #icon>
            <el-icon><LineMdPlus /></el-icon>
          </template>
          <template v-else #icon>
            <el-icon><LineMdEdit /></el-icon>
          </template>
          {{ props.dealerRoleId ? '修改' : '新增' }}
        </el-button>
      </div>
    </el-form>
  </div>
</template>

<style lang="scss" scoped>
.add-role-container {
  .menu-tree-container {
    min-width: 100%;
    max-height: 400px;

    overflow-y: auto;
    border: 1px solid #ebeef5;
    border-radius: 4px;
    padding: 10px;

    .control-container {
      padding-bottom: 10px;
      border-bottom: 1px solid #ebeef5;
      margin-bottom: 10px;
      display: flex;
      align-items: center;
      gap: 20px;

      .control-item {
        display: flex;
        align-items: center;

        .el-checkbox {
          font-weight: 600;
          font-size: 14px;
        }
      }
    }
  }

  .custom-tree-node {
    display: flex;
    align-items: center;

    .el-icon {
      margin-right: 6px;
      font-size: 16px;
    }

    .menu-text {
      font-size: 14px;
    }
  }
  .buttons {
    width: 100%;
    display: flex;
    justify-content: flex-end;
  }
}
</style>
